package JUC.lock锁;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author CKC
 * @DateTime 2021/3/15 18:21
 * <p>
 * 题目：现在两个线程，可以操作初始值为零的额一个变量
 * 实现一个线程对该变量加一，一个线程对该变量减1，实现交替，来10轮，变量初始值为 0
 * 1.高内聚低耦合前提下，线程操作资源类
 * 2.判断+干活+通知
 * 3.防止线程虚假唤醒，只要有wait需要while判断
 * <p>
 * 知识小总结===>  多线程编程套路  + while判断+ 新版写法
 */
public class ProConsumerDemo04 {
    public static void main(String[] args) {
        AirCondition aircondition = new AirCondition();
        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    aircondition.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        
        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    aircondition.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Son").start();
        
        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    aircondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();
        
        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    aircondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();
        
    }
}

class AirCondition {
    private int number = 0;
    /**
     * 老版的
     */
/*    public synchronized void increment() throws InterruptedException {
        //判断
        while (number != 0) {
            this.wait();
        }
        //干活
        number++;
        //通知
        System.out.println(Thread.currentThread().getName() + "\t" + number);
        this.notifyAll();
    }
    
    public synchronized void decrement() throws InterruptedException {
        //判断
        while (number == 0) {
            this.wait();
        }
        //干活
        number--;
        //通知
        System.out.println(Thread.currentThread().getName() + "\t" + number);
        this.notifyAll();
    }*/
    
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    
    public void increment() throws InterruptedException {
        
        lock.lock();
        try {
            //判断
            while (number != 0) {
               condition.await(); // this.wait();
            }
            //干活
            number++;
            //通知
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            condition.signalAll();//this.notifyAll();
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
    public void decrement() throws InterruptedException {
        
        lock.lock();
        try {
            //判断
            while (number == 0) {
                condition.await(); // this.wait();
            }
            //干活
            number--;
            //通知
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            condition.signalAll();//this.notifyAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
}